home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -screenplay- / shareware / warpquake / warpquakesrc / gl_refrag.c < prev    next >
C/C++ Source or Header  |  2000-02-29  |  4KB  |  235 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_efrag.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. mnode_t    *r_pefragtopnode;
  25.  
  26.  
  27. //===========================================================================
  28.  
  29. /*
  30. ===============================================================================
  31.  
  32.                     ENTITY FRAGMENT FUNCTIONS
  33.  
  34. ===============================================================================
  35. */
  36.  
  37. efrag_t        **lastlink;
  38.  
  39. vec3_t        r_emins, r_emaxs;
  40.  
  41. entity_t    *r_addent;
  42.  
  43.  
  44. /*
  45. ================
  46. R_RemoveEfrags
  47.  
  48. Call when removing an object from the world or moving it to another position
  49. ================
  50. */
  51. void R_RemoveEfrags (entity_t *ent)
  52. {
  53.     efrag_t        *ef, *old, *walk, **prev;
  54.     
  55.     ef = ent->efrag;
  56.     
  57.     while (ef)
  58.     {
  59.         prev = &ef->leaf->efrags;
  60.         while (1)
  61.         {
  62.             walk = *prev;
  63.             if (!walk)
  64.                 break;
  65.             if (walk == ef)
  66.             {    // remove this fragment
  67.                 *prev = ef->leafnext;
  68.                 break;
  69.             }
  70.             else
  71.                 prev = &walk->leafnext;
  72.         }
  73.                 
  74.         old = ef;
  75.         ef = ef->entnext;
  76.         
  77.     // put it on the free list
  78.         old->entnext = cl.free_efrags;
  79.         cl.free_efrags = old;
  80.     }
  81.     
  82.     ent->efrag = NULL; 
  83. }
  84.  
  85. /*
  86. ===================
  87. R_SplitEntityOnNode
  88. ===================
  89. */
  90. void R_SplitEntityOnNode (mnode_t *node)
  91. {
  92.     efrag_t        *ef;
  93.     mplane_t    *splitplane;
  94.     mleaf_t        *leaf;
  95.     int            sides;
  96.     
  97.     if (node->contents == CONTENTS_SOLID)
  98.     {
  99.         return;
  100.     }
  101.     
  102. // add an efrag if the node is a leaf
  103.  
  104.     if ( node->contents < 0)
  105.     {
  106.         if (!r_pefragtopnode)
  107.             r_pefragtopnode = node;
  108.  
  109.         leaf = (mleaf_t *)node;
  110.  
  111. // grab an efrag off the free list
  112.         ef = cl.free_efrags;
  113.         if (!ef)
  114.         {
  115.             Con_Printf ("Too many efrags!\n");
  116.             return;        // no free fragments...
  117.         }
  118.         cl.free_efrags = cl.free_efrags->entnext;
  119.  
  120.         ef->entity = r_addent;
  121.         
  122. // add the entity link    
  123.         *lastlink = ef;
  124.         lastlink = &ef->entnext;
  125.         ef->entnext = NULL;
  126.         
  127. // set the leaf links
  128.         ef->leaf = leaf;
  129.         ef->leafnext = leaf->efrags;
  130.         leaf->efrags = ef;
  131.             
  132.         return;
  133.     }
  134.     
  135. // NODE_MIXED
  136.  
  137.     splitplane = node->plane;
  138.     sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
  139.     
  140.     if (sides == 3)
  141.     {
  142.     // split on this plane
  143.     // if this is the first splitter of this bmodel, remember it
  144.         if (!r_pefragtopnode)
  145.             r_pefragtopnode = node;
  146.     }
  147.     
  148. // recurse down the contacted sides
  149.     if (sides & 1)
  150.         R_SplitEntityOnNode (node->children[0]);
  151.         
  152.     if (sides & 2)
  153.         R_SplitEntityOnNode (node->children[1]);
  154. }
  155.  
  156.  
  157.  
  158. /*
  159. ===========
  160. R_AddEfrags
  161. ===========
  162. */
  163. void R_AddEfrags (entity_t *ent)
  164. {
  165.     model_t        *entmodel;
  166.     int            i;
  167.         
  168.     if (!ent->model)
  169.         return;
  170.  
  171.     r_addent = ent;
  172.             
  173.     lastlink = &ent->efrag;
  174.     r_pefragtopnode = NULL;
  175.     
  176.     entmodel = ent->model;
  177.  
  178.     for (i=0 ; i<3 ; i++)
  179.     {
  180.         r_emins[i] = ent->origin[i] + entmodel->mins[i];
  181.         r_emaxs[i] = ent->origin[i] + entmodel->maxs[i];
  182.     }
  183.  
  184.     R_SplitEntityOnNode (cl.worldmodel->nodes);
  185.  
  186.     ent->topnode = r_pefragtopnode;
  187. }
  188.  
  189.  
  190. /*
  191. ================
  192. R_StoreEfrags
  193.  
  194. // FIXME: a lot of this goes away with edge-based
  195. ================
  196. */
  197. void R_StoreEfrags (efrag_t **ppefrag)
  198. {
  199.     entity_t    *pent;
  200.     model_t        *clmodel;
  201.     efrag_t        *pefrag;
  202.  
  203.  
  204.     while ((pefrag = *ppefrag) != NULL)
  205.     {
  206.         pent = pefrag->entity;
  207.         clmodel = pent->model;
  208.  
  209.         switch (clmodel->type)
  210.         {
  211.         case mod_alias:
  212.         case mod_brush:
  213.         case mod_sprite:
  214.             pent = pefrag->entity;
  215.  
  216.             if ((pent->visframe != r_framecount) &&
  217.                 (cl_numvisedicts < MAX_VISEDICTS))
  218.             {
  219.                 cl_visedicts[cl_numvisedicts++] = pent;
  220.  
  221.             // mark that we've recorded this entity for this frame
  222.                 pent->visframe = r_framecount;
  223.             }
  224.  
  225.             ppefrag = &pefrag->leafnext;
  226.             break;
  227.  
  228.         default:    
  229.             Sys_Error ("R_StoreEfrags: Bad entity type %d\n", clmodel->type);
  230.         }
  231.     }
  232. }
  233.  
  234.  
  235.